package com.alibaba.cirtus.ots.application.adapter.ability.facade.serviceV2.nyk;

import com.alibaba.cirtus.ots.application.adapter.ability.model.enums.NykFailRecordEnum;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.model.dto.BaselineGetOrganizationByCodes2Request;
import com.epoch.app.bcorder.model.dto.BaselineGetOrganizationByCodes2Response;
import com.epoch.app.bcorder.model.dto.BaselineGetOrganizationById2Request;
import com.epoch.app.bcorder.model.dto.OrganizationSDO;
import com.epoch.app.bcorder.service.BaseDataService;
import com.epoch.app.otsapplicationadaptersdk.model.dto.NykSaleOrderRisePageData;
import com.epoch.app.otsapplicationadaptersdk.model.dto.RestNykSaleOrderDataRiseRequest;
import com.epoch.app.otsapplicationadaptersdk.model.dto.RestNykSaleOrderDataRiseResponse;
import com.epoch.app.otsapplicationadaptersdk.nyk.NykSaleOrder;
import com.epoch.app.otsapplicationadaptersdk.nyk.mnnyksaleorder.dto.DoHandlerRequest;
import com.epoch.app.otsapplicationadaptersdk.nyk.mnnyksaleorderrise.dto.UpdateAllRiseDataRequest;
import com.epoch.app.otsapplicationadaptersdk.nyk.mnnyksaleorderrise.dto.UpdateAllRiseDataResponse;
import com.epoch.app.otsapplicationadaptersdk.nyk.mnnyksaleorderrise.dto.UpdateoAllocateOrderOutOrderIdRequest;
import com.epoch.app.otsapplicationadaptersdk.nyk.mnnyksaleorderrise.service.MnNykSaleOrderRiseService;
import com.epoch.app.otsapplicationadaptersdk.service.NykService;
import com.epoch.app.crunifiedinventory.api.allocateorderwrite.service.AllocateOrderWriteService;
import com.epoch.app.crunifiedinventory.domain.allocateorder.model.AllocateOrder;
import com.epoch.app.crunifiedinventory.domain.allocateorder.service.AllocateOrderService;
import com.epoch.app.crunifiedinventory.model.dto.LoadNykErrorListRequest;
import com.epoch.app.crunifiedinventory.model.dto.NykSaleOrderRise;
import com.epoch.app.crunifiedinventory.model.dto.NykSaleOrderRiseList;
import com.epoch.app.crunifiedinventory.ouinykfailrecord.model.OuiNykFailRecord;
import com.epoch.app.crunifiedinventory.ouinykfailrecord.service.OuiNykFailRecordService;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Component
public class MnNykSaleOrderRiseV2ServiceImpl implements MnNykSaleOrderRiseService {
    private final Log log = Log.getLogger(MnNykSaleOrderRiseV2ServiceImpl.class);

    @Resource
    private NykService nykService;

    @Autowired
    private BaseDataService baseDataService;

    @Resource
    private AllocateOrderWriteService allocateOrderWriteService;

    @Autowired
    private OuiNykFailRecordService ouiNykFailRecordService;

    @Autowired
    private AllocateOrderService allocateOrderService;

    private void createErrorLog(String failureReason, NykSaleOrder record, DoHandlerRequest doHandlerRequest){
        OuiNykFailRecord request = new OuiNykFailRecord();
        request.setFeatures(JSONObject.toJSONString(record));
        request.setFailureReason(failureReason);
        request.setQueryRequest(JSONObject.toJSONString(doHandlerRequest));
        request.setType(NykFailRecordEnum.SALE.getValue());
        request.setSubId(record.getVbapPosnr());
        request.setOrderId(record.getHeadId());
        ouiNykFailRecordService.create(request);
    }

    @Override
    public Result<Boolean> updateoAllocateOrderOutOrderId(UpdateoAllocateOrderOutOrderIdRequest updateoAllocateOrderOutOrderIdRequest) {
        //根据入参查找牛要客数据
        RestNykSaleOrderDataRiseRequest restNykSaleOrderDataRiseRequest = new RestNykSaleOrderDataRiseRequest();
        restNykSaleOrderDataRiseRequest.setQueryDate(updateoAllocateOrderOutOrderIdRequest.getQueryDate());
        restNykSaleOrderDataRiseRequest.setCurrent(updateoAllocateOrderOutOrderIdRequest.getCurrent());
        restNykSaleOrderDataRiseRequest.setSize("500");
        log.info("MnNykSaleOrderRiseServiceImpl.updateoAllocateOrderOutOrderId.restNykSaleOrderDataRise,request:{}", JSON.toJSONString(restNykSaleOrderDataRiseRequest));
        RestNykSaleOrderDataRiseResponse response = nykService.restNykSaleOrderDataRise(restNykSaleOrderDataRiseRequest);
        log.info("MnNykSaleOrderRiseServiceImpl.updateoAllocateOrderOutOrderId.restNykSaleOrderDataRise,result:{}", JSON.toJSONString(response));

        Integer resulTotal = 0;
        List<NykSaleOrderRise> nykSaleOrderRiseAll = new ArrayList<>();
        if (Objects.nonNull(response)&&Objects.nonNull(response.getResult())&& Objects.nonNull(response.getResult().getData())){
            NykSaleOrderRisePageData nykSaleOrderRisePageData = response.getResult().getData();
            if (Objects.nonNull(nykSaleOrderRisePageData)){
                Integer page = response.getResult().getData().getPages();
                List<NykSaleOrderRise> nykSaleOrderRises = updateUpdateoAllocateOrderOutOrderId(nykSaleOrderRisePageData);
                if (CollectionUtils.isNotEmpty(nykSaleOrderRises)){
                    nykSaleOrderRiseAll.addAll(nykSaleOrderRises);
                    resulTotal = resulTotal+nykSaleOrderRises.size();
                }
                for (Integer j = 2; j <= page; j++) {
                    RestNykSaleOrderDataRiseRequest restNykSaleOrderDataRise = new RestNykSaleOrderDataRiseRequest();
                    restNykSaleOrderDataRise.setQueryDate(updateoAllocateOrderOutOrderIdRequest.getQueryDate());
                    restNykSaleOrderDataRise.setCurrent(j.toString());
                    restNykSaleOrderDataRise.setSize("500");
                    response = nykService.restNykSaleOrderDataRise(restNykSaleOrderDataRise);
                    if (Objects.nonNull(response)&&Objects.nonNull(response.getResult())&& Objects.nonNull(response.getResult().getData())) {
                        nykSaleOrderRisePageData = response.getResult().getData();
                        List<NykSaleOrderRise> nykSaleOrderRiseList = updateUpdateoAllocateOrderOutOrderId(nykSaleOrderRisePageData);
                        if (CollectionUtils.isNotEmpty(nykSaleOrderRises)) {
                            nykSaleOrderRiseAll.addAll(nykSaleOrderRiseList);
                            resulTotal = resulTotal + nykSaleOrderRiseList.size();
                        }
                    }
                }
            }
        }
        //查询一周内牛要客失败数据
        LoadNykErrorListRequest loadNykErrorListRequest = new LoadNykErrorListRequest();
        loadNykErrorListRequest.setType("2");
        String applyOrgId = getOrgOutCodeByHeadquartersCode("6140");
        //2022.3.15 调拨单提报组织统一为分子公司.
        if (StringUtils.isNotBlank(applyOrgId)){
            BaselineGetOrganizationById2Request baselineGetOrganizationById2Request =
                    new BaselineGetOrganizationById2Request();
            baselineGetOrganizationById2Request.setId(applyOrgId);
            Result<OrganizationSDO> organizationSDOResult = baseDataService.baselineGetOrganizationById2(baselineGetOrganizationById2Request);
            if (organizationSDOResult != null && organizationSDOResult.getResult() != null
                && Objects.equals(organizationSDOResult.getResult().getType(),104)){
                applyOrgId = organizationSDOResult.getResult().getParentId();
            }
        }
        loadNykErrorListRequest.setApplyOrgId(applyOrgId);
        Result<List<AllocateOrder>> listResult = allocateOrderService.loadNykErrorList(loadNykErrorListRequest);
        log.info("MnNykSaleOrderRiseServiceImpl.updateoAllocateOrderOutOrderId.loadNykErrorList,result:{}", JSON.toJSONString(listResult));
        if (Objects.nonNull(listResult)&&CollectionUtils.isNotEmpty(listResult.getResult())){
            List<AllocateOrder> allocateOrders = listResult.getResult();
            //循环牛要客失败数据
            for (AllocateOrder allocateOrder:allocateOrders){
                //根据牛要客id查找牛要客数据
                RestNykSaleOrderDataRiseRequest restNykSaleOrderDataRise = new RestNykSaleOrderDataRiseRequest();
                restNykSaleOrderDataRise.setId(allocateOrder.getOutAllocateOrderId());
                log.info("MnNykSaleOrderRiseServiceImpl.updateoAllocateOrderOutOrderId_restNykSaleOrderDataRise,request:{}", JSON.toJSONString(restNykSaleOrderDataRise));
                RestNykSaleOrderDataRiseResponse restNykSaleOrderDataRiseResponse = nykService.restNykSaleOrderDataRise(restNykSaleOrderDataRise);
                log.info("MnNykSaleOrderRiseServiceImpl.updateoAllocateOrderOutOrderId_restNykSaleOrderDataRise,result:{}", JSON.toJSONString(restNykSaleOrderDataRiseResponse));
                if (Objects.nonNull(restNykSaleOrderDataRiseResponse)&&Objects.nonNull(restNykSaleOrderDataRiseResponse.getResult())&& Objects.nonNull(restNykSaleOrderDataRiseResponse.getResult().getData())) {
                    NykSaleOrderRisePageData nykSaleOrderRisePage = restNykSaleOrderDataRiseResponse.getResult().getData();
                    if (Objects.nonNull(nykSaleOrderRisePage)) {
                        //保存牛要客数据
                        updateUpdateoAllocateOrderOutOrderId(nykSaleOrderRisePage);
                    }
                }
            }
        }
        Result result = new Result();
        result.setSuccess(true);
        result.setTotal(resulTotal);
        result.setResult(nykSaleOrderRiseAll);
        return result;
    }


    @Override
    public UpdateAllRiseDataResponse updateAllRiseData(UpdateAllRiseDataRequest updateAllRiseDataRequest){
        UpdateAllRiseDataResponse response = new UpdateAllRiseDataResponse();

        int successDayCount=0;
        int failedDayCount=0;
        int dayCount=0;
        String endDate = updateAllRiseDataRequest.getEndDate();
        if (StringUtils.isBlank(endDate)){
            endDate=String.valueOf(LocalDate.now());;
        }

        List<String> dateList = collectLocalDates(updateAllRiseDataRequest.getStartDate(), endDate);

        UpdateoAllocateOrderOutOrderIdRequest doHandlerRequest = new UpdateoAllocateOrderOutOrderIdRequest();

        for (String oneDay : dateList) {
            doHandlerRequest.setQueryDate(oneDay);
            doHandlerRequest.setSize("500");
            Result<Boolean> booleanResult = updateoAllocateOrderOutOrderId(doHandlerRequest);
            if (Objects.nonNull(booleanResult)&&booleanResult.isSuccess()){
                successDayCount+=booleanResult.getTotal();
            }else {
                failedDayCount+=booleanResult.getTotal();
            }
            dayCount+=booleanResult.getTotal();

        }
        response.setSuccessCount(String.valueOf(successDayCount));
        response.setFailedCount(String.valueOf(failedDayCount));
        response.setCount(String.valueOf(dayCount));
        return response;
    }


    private List<NykSaleOrderRise> updateUpdateoAllocateOrderOutOrderId(NykSaleOrderRisePageData nykSaleOrderRisePageData){
        List<NykSaleOrderRise> nykSaleOrderRises = new ArrayList<>();
        if (Objects.nonNull(nykSaleOrderRisePageData)) {
            for (com.epoch.app.otsapplicationadaptersdk.model.dto.NykSaleOrderRise nykSaleOrderRise : nykSaleOrderRisePageData.getRecords()) {
                NykSaleOrderRise nykSaleOrderRiseNew = new NykSaleOrderRise();
                nykSaleOrderRiseNew.setId(nykSaleOrderRise.getId());
                nykSaleOrderRiseNew.setVbakVbeln(nykSaleOrderRise.getVbakVbeln());
                nykSaleOrderRises.add(nykSaleOrderRiseNew);
            }
        }
        //调用调拨单接口更新
        List<NykSaleOrderRise> list = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(nykSaleOrderRises)) {
            NykSaleOrderRiseList nykSaleOrderRiseList = new NykSaleOrderRiseList();
            nykSaleOrderRiseList.setList(nykSaleOrderRises);
            log.info("MnNykSaleOrderRiseServiceImpl.updateoAllocateOrderOutOrderId.nykUpdateoAllocateOrderOutOrderId,request:{}", JSON.toJSONString(nykSaleOrderRiseList));
            Result<List<NykSaleOrderRise>> listResult = allocateOrderWriteService.nykUpdateoAllocateOrderOutOrderId(nykSaleOrderRiseList);
            if (Objects.nonNull(listResult)){
                list = listResult.getResult();
            }
        }
        return list;
    }
    private String getOrgOutCodeByHeadquartersCode(String soldPartCode){
        BaselineGetOrganizationByCodes2Request baselineGetOrganizationByCodes2Request = new BaselineGetOrganizationByCodes2Request();
        baselineGetOrganizationByCodes2Request.setIds(Lists.newArrayList(soldPartCode));
        BaselineGetOrganizationByCodes2Response baselineGetOrganizationByCodes2Response = baseDataService.baselineGetOrganizationByCodes2(baselineGetOrganizationByCodes2Request);
        if (Objects.nonNull(baselineGetOrganizationByCodes2Response)&& org.apache.commons.collections4.CollectionUtils.isNotEmpty(baselineGetOrganizationByCodes2Response.getResult())){
            String outcode = baselineGetOrganizationByCodes2Response.getResult().get(0).getId();
            if (org.apache.commons.lang.StringUtils.isNotBlank(outcode)){
                return outcode;
            }
        }
        return "";
    }

    /**
     * 收集起始时间到结束时间之间所有的时间并以字符串集合方式返回
     *
     * @param timeStart
     * @param timeEnd
     * @return
     */
    private static List<String> collectLocalDates(String timeStart, String timeEnd) {
        return collectLocalDates(LocalDate.parse(timeStart), LocalDate.parse(timeEnd));
    }

    /**
     * 收集起始时间到结束时间之间所有的时间并以字符串集合方式返回
     *
     * @param start
     * @param end
     * @return
     */
    private static List<String> collectLocalDates(LocalDate start, LocalDate end) {
        // 用起始时间作为流的源头，按照每次加一天的方式创建一个无限流
        return Stream.iterate(start, localDate -> localDate.plusDays(1))
                // 截断无限流，长度为起始时间和结束时间的差+1个
                .limit(ChronoUnit.DAYS.between(start, end) + 1)
                // 由于最后要的是字符串，所以map转换一下
                .map(LocalDate::toString)
                // 把流收集为List
                .collect(Collectors.toList());
    }
}
